Published on

领域驱动设计实践中如何组织代码

Authors
  • avatar
    Name
    Qiu Yuzhou
    Twitter

以golang语言为例,介绍在领域驱动设计的开发的实现中如何组织代码。

模块化单体项目

上层结构按界限上下文(Bounded Conetext)分子目录/子包

目录结构类似如下:

bounded-contexts/
├── account
├── asset
├── customer
├── invoice
├── payment
├── paymentv2
├── bookkeeping
├── historder
├── orderinsur
├── virtualphone
├── ...

界限上下文(Bounded Conetext)内分层架构

界限上下文(Bounded Conetext)中参考分层架构(Layered Architecture)六边形架构(Hexagonal architecture pattern)分子目录/子包。

account/
├── domain
├── app
├── adapters
├── entrypoints

界限上下文(Bounded Conetext)内的代码分为由内到外3层:

  • 领域层,包含领域模型和领域服务
  • 应用层,包含应用服务,也叫用例层
  • 最外层,包含各种接口适配器。包括且不限于:数据库适配器、消息队列适配器、HTTP API适配器、gRPC适配器等

依赖与隔离

外层代码可以依赖内层和同层,内层不能依赖外层。 必要时使用接口以实现依赖反转。比如,领域层定义实体的持久化接口,在最外层接口实现中调用数据库SDK。

  • 领域层仅包含领域逻辑,不包含任何外部依赖。
  • 应用层包含应用逻辑,调用领域层。并且附加如身份验证、权限控制、操作审计等应用逻辑。
  • 最外层包含外部依赖的适配器,如数据库的访问代码、消息队列的处理回调、HTTP API的实现、外部系统API调用等。

界限上下文(Bounded Conetext)的代码依赖关系应该尽量减少,尽量通过事件驱动等方式实现。 总之,界限上下文中可以用数据库事务实现多个实体的一致性,跨界限上下文则通过事件实现最终一致性。 这样当随着项目长期迭代后,更容易将个别界限上下文拆分到独立的微服务项目中。

参考引用

  1. Bounded Context
  2. Wikipedia: Hexagonal architecture
  3. Book: Clean Architecture: A Craftsman's Guide to Software Structure and Design